package com.iflytek.autofly.setting.biz.system;

import android.content.Context;
import android.text.TextUtils;

import com.iflytek.autofly.bluetoothservice.util.BluetoothServiceCons.AidlStatus;
import com.iflytek.autofly.systemservice.util.FlySystemManager;
import com.iflytek.autofly.systemservice.util.ISystemListener;
import com.iflytek.autofly.systemupdate.aidl.UpdatePackageInfo;
import com.iflytek.autofly.systemupdate.manager.ResultCode;
import com.iflytek.autofly.systemupdate.manager.SystemUpdateCallback;
import com.iflytek.autofly.systemupdate.manager.SystemUpdateManager;
import com.iflytek.autofly.utils.FlyLog;

/**
 * <b>Description: </b>系统更新<br/>
 * <b>Change History:</b><br/>
 * <table border="1">
 * <tr>
 * <td><b>user</b></td>
 * <td><b>date</b></td>
 * <td><b>time</b></td>
 * <td><b>reason</b></td>
 * </tr>
 * <tr>
 * <td>JunLuan@iflytek.com</td>
 * <td>2015年5月26日</td>
 * <td>上午11:23:16</td>
 * <td>创建此文件</td>
 * </tr>
 * </table>
 *
 * @author JunLuan@iflytek.com
 */
public class SystemUpdater {
    private static final String TAG = "SystemUpdater";
    private Context mContext;
    private OnSystemUpdaterChanged mOnSystemUpdaterChanged;
    private SystemUpdateManager mSysUpdater;
    private int mSysUpdateState = SYS_UPDATE_STATE.INIT;
    private UpdatePackageInfo mPackageInfo;
    private int mDownloadFailedReason;
    private SystemUpdateCallback mSystemUpdateCallback;
    private FlySystemManager mMngr;
    private String mUpdateInfo = "";

    private SystemUpdater() {
    }

    public static SystemUpdater getInstance() {
        return SystemUpdaterInstance.INSTANCE;
    }

    /**
     * init:初始化. <br/>
     *
     * @param ctx context
     * @param l   listener
     */
    public void init(Context ctx, OnSystemUpdaterChanged l) {
        FlyLog.d(TAG, "in");

        mOnSystemUpdaterChanged = l;

        if (ctx == mContext) {
            getWorkState();
            FlyLog.d(TAG, "out");
            return;
        }

        if (mContext != null) {
            fini();
        }

        FlyLog.d(TAG, "createClient");

        mContext = ctx;

        mSysUpdater = SystemUpdateManager.getInstance(ctx);

        if (mSystemUpdateCallback == null) {
            mSystemUpdateCallback = new SystemUpdateCallback() {
                @Override
                public void onServiceStateChanged(int state) {
                    switch (state) {
                        case ResultCode.SERVICE_BINDED:
                            getWorkState();
                            return;
                        case ResultCode.SERVICE_UNBINDED:
                            FlyLog.e(TAG, "SERVICE_UNBINDED");
                            mSysUpdateState = SYS_UPDATE_STATE.CHECK_FAILED;
                            if (mOnSystemUpdaterChanged != null) {
                                mOnSystemUpdaterChanged
                                        .onSystemUpdateStateChanged(mSysUpdateState);
                            }
                            return;
                        case ResultCode.SERVICE_BINDING:
                            return;
                        default:
                            FlyLog.e(TAG, "unknown state " + state);
                            return;
                    }
                }

                @Override
                public void onCheckComplete(int resultCode) {
                    FlyLog.d(TAG, "resultCode=" + resultCode);
                    switch (resultCode) {
                        case ResultCode.UPDATE_AVAILABLE:
                            FlyLog.d(TAG, "UPDATE_AVAILABLE");
                            mSysUpdateState = SYS_UPDATE_STATE.CHECKED;
                            mPackageInfo = mSysUpdater.getUpdatePackageInfo();
                            mSysUpdater.fetchReleaseNotes();
                            break;
                        case ResultCode.UPDATE_UNAVAILABLE:
                            FlyLog.d(TAG, "UPDATE_UNAVAILABLE");
                            mPackageInfo = null;
                            mSysUpdateState = SYS_UPDATE_STATE.CHECKED;
                            break;
                        case ResultCode.SERVER_ERROR:
                            FlyLog.e(TAG, "SERVER_ERROR");
                            mSysUpdateState = SYS_UPDATE_STATE.CHECK_FAILED;
                            break;
                        case ResultCode.HTTP_EXECUTE_ERROR:
                            FlyLog.e(TAG, "HTTP_EXECUTE_ERROR");
                            mSysUpdateState = SYS_UPDATE_STATE.CHECK_FAILED;
                            break;
                        case ResultCode.HTTP_CONNECT_TIMEOUT:
                            FlyLog.e(TAG, "HTTP_CONNECT_TIMEOUT");
                            mSysUpdateState = SYS_UPDATE_STATE.CHECK_FAILED;
                            break;
                    }

                    if (mOnSystemUpdaterChanged != null) {
                        mOnSystemUpdaterChanged
                                .onSystemUpdateStateChanged(mSysUpdateState);
                    }
                }

                @Override
                public void onDescFetched(int resultCode, String info) {
                    FlyLog.d(TAG, "enter");
                    if (resultCode == ResultCode.RESULT_OK) {
                        mUpdateInfo = info;
                    }
                }

                @Override
                public void onDownloadPaused() {
                    FlyLog.d(TAG, "enter");
                    mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_PAUSED;
                    if (mOnSystemUpdaterChanged != null) {
                        mOnSystemUpdaterChanged
                                .onSystemUpdateStateChanged(mSysUpdateState);
                    }
                }

                @Override
                public void onProgressChanged(float progress) {
                    FlyLog.d(TAG, "progress=" + progress);
                    if (mSysUpdateState != SYS_UPDATE_STATE.DOWNLOADING) {
                        mSysUpdateState = SYS_UPDATE_STATE.DOWNLOADING;
                        if (mOnSystemUpdaterChanged != null) {
                            mOnSystemUpdaterChanged
                                    .onSystemUpdateStateChanged(mSysUpdateState);
                        }
                    }
                    if (mOnSystemUpdaterChanged != null) {
                        mOnSystemUpdaterChanged
                                .onSystemUpdateProgressChanged((int) (progress * 100));
                    }
                }

                public void onDownloadComplete(int resultCode) {
                    FlyLog.d(TAG, "resultCode=" + resultCode);
                    mDownloadFailedReason = resultCode;
                    switch (resultCode) {
                        case ResultCode.DOWNLOAD_SUCCESS:
                            FlyLog.d(TAG, "DOWNLOAD_SUCCESS");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOADED;
                            break;
                        case ResultCode.IO_FAILED:
                            FlyLog.e(TAG, "IO_FAILED");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                            break;
                        case ResultCode.MD5_CHECK_FAILED:
                            FlyLog.e(TAG, "MD5_CHECK_FAILED");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                            break;
                        case ResultCode.SD_NOT_MOUNTED:
                            FlyLog.e(TAG, "SD_NOT_MOUNTED");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                            break;
                        case ResultCode.SD_READ_ONLY:
                            FlyLog.e(TAG, "SD_READ_ONLY");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                            break;
                        case ResultCode.SPACE_NOT_ENOUGH:
                            FlyLog.e(TAG, "SPACE_NOT_ENOUGH");
                            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                            break;
                    }
                    if (mOnSystemUpdaterChanged != null) {
                        mOnSystemUpdaterChanged
                                .onSystemUpdateStateChanged(mSysUpdateState);
                    }
                }
            };
        }
        mSysUpdater.createClient(mSystemUpdateCallback);

        FlyLog.d(TAG, "out");
    }

    void getWorkState() {
        int workState = mSysUpdater.getWorkState();
        FlyLog.d(TAG, "workState " + workState);
        switch (workState) {
            case ResultCode.STATE_NEED_CHECK:
                mSysUpdateState = SYS_UPDATE_STATE.INIT;
                break;
            case ResultCode.STATE_DOWNLOADING:
                mSysUpdateState = SYS_UPDATE_STATE.DOWNLOADING;
                mSysUpdater.fetchReleaseNotes();
                break;
            case ResultCode.STATE_DOWNLOAD_SUCCESS:
                mSysUpdateState = SYS_UPDATE_STATE.DOWNLOADED;
                mSysUpdater.fetchReleaseNotes();
                break;
            case ResultCode.STATE_DOWNLOAD_FAILED:
                mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_FAILED;
                mSysUpdater.fetchReleaseNotes();
                break;
            case ResultCode.STATE_DOWNLOADING_PAUSED:
                mSysUpdateState = SYS_UPDATE_STATE.DOWNLOAD_PAUSED;
                mSysUpdater.fetchReleaseNotes();
                break;
            case ResultCode.STATE_BINDER_ERROR:
                FlyLog.e(TAG, "getWorkState: STATE_BINDER_ERROR");
                mSysUpdateState = SYS_UPDATE_STATE.CHECK_FAILED;
                break;
            default:
                FlyLog.e(TAG, "getWorkState: unknown state"
                        + workState);
                mSysUpdateState = SYS_UPDATE_STATE.INIT;
                break;
        }
        if (mOnSystemUpdaterChanged != null) {
            mOnSystemUpdaterChanged
                    .onSystemUpdateStateChanged(mSysUpdateState);
        }
    }

    /**
     * fini:逆初始化. <br/>
     */
    public void fini() {
        if (mSysUpdater != null) {
            mSysUpdater.destroyClient();
        }
        mSysUpdater = null;
        mOnSystemUpdaterChanged = null;
        mContext = null;
    }

    /**
     * getSystemUpdateDataSize:get the size of system update package. <br/>
     *
     * @return 更新包大小，单位M, 0表示无更新
     */
    public long getSystemUpdateDataSize() {
        if (mPackageInfo == null) {
            mPackageInfo = mSysUpdater.getUpdatePackageInfo();
        }
        if (mPackageInfo != null) {
            return mPackageInfo.getPackageSize();
        }
        return 0;
    }

    /**
     * getSystemUpdateVersion:get the version of system update package. <br/>
     *
     * @return 版本号
     */
    public String getSystemUpdateVersion() {
        if (mPackageInfo == null) {
            mPackageInfo = mSysUpdater.getUpdatePackageInfo();
        }
        if (mPackageInfo != null) {
            return mPackageInfo.getVnName();
        }
        return "";
    }

    /**
     * updateSystem:开始更新系统. <br/>
     *
     * @return 是否成功
     */
    public boolean updateSystem(Context c, ISysUpdateListener ll) {
        if (c == null || ll == null) {
            FlyLog.e(TAG, "args null: Context=" + c + ",ISysUpdateListener="
                    + ll);
            return false;
        }
        final ISysUpdateListener l = ll;
        if (mSysUpdateState == SYS_UPDATE_STATE.DOWNLOADED) {
            final String path = mSysUpdater.getPkgPath();
            if (!TextUtils.isEmpty(path)) {
                mMngr = FlySystemManager.registerListener(c,
                        new ISystemListener() {

                            @Override
                            public void onServiceStatusChanged(int status) {
                                if (status == AidlStatus.SERVICE_AIDL_BOUND) {
                                    if (mMngr != null) {
                                        mMngr.updateSystem(path);
                                    }
                                } else if (status == AidlStatus.SERVICE_AIDL_NOT_BOUND) {
                                    l.onError(false, -1);
                                }
                            }

                            @Override
                            public void onError(int result) {
                                if (result != 0) {
                                    l.onError(false, result);
                                }
                            }

                            @Override
                            public void onProgress(int i, int i1) {
                            }
                        });
                if (mMngr != null) {
                    return true;
                }
                FlyLog.e(TAG, "updateSystem failed: mngr is null");
                return false;
            } else {
                FlyLog.e(TAG, "path is null");
            }
        } else {
            FlyLog.e(TAG, "state error: " + mSysUpdateState);
        }
        return false;
    }

    /**
     * getSystemUpdateState:获取系统更新的状态. <br/>
     *
     * @return 系统更新的状态
     * @see SYS_UPDATE_STATE
     */
    public int getSystemUpdateState() {
        return mSysUpdateState;
    }

    /**
     * getSystemUpdateDownloadFailedReason:获取系统更新下载失败的原因. <br/>
     *
     * @return 失败的原因
     */
    public int getSystemUpdateDownloadFailedReason() {
        return mDownloadFailedReason;
    }

    /**
     * getSystemUpdateProgress:获取系统更新的进度. <br/>
     *
     * @return 进度， 0～100
     */
    public int getSystemUpdateProgress() {
        FlyLog.d(TAG, "enter");
        if (mSysUpdateState == SYS_UPDATE_STATE.DOWNLOADING
                || mSysUpdateState == SYS_UPDATE_STATE.DOWNLOAD_PAUSED) {
            float rate = mSysUpdater.getDownloadRate();
            int progress = (int) (rate * 100);
            FlyLog.d(TAG, "rate=" + rate + ",progress=" + progress);
            return (int) (mSysUpdater.getDownloadRate() * 100);
        }
        return 0;
    }

    /**
     * startDownloadSystemUpdate:开始下载更新包. <br/>
     */
    public void startDownloadSystemUpdate() {
        FlyLog.d(TAG, "enter|mSysUpdateState=" + mSysUpdateState);
        if (mSysUpdateState == SYS_UPDATE_STATE.CHECKED
                || mSysUpdateState == SYS_UPDATE_STATE.DOWNLOAD_FAILED
                || mSysUpdateState == SYS_UPDATE_STATE.DOWNLOAD_PAUSED) {
            //if (mPackageInfo != null) {
            mSysUpdateState = SYS_UPDATE_STATE.DOWNLOADING;
            if (mOnSystemUpdaterChanged != null) {
                mOnSystemUpdaterChanged
                        .onSystemUpdateStateChanged(mSysUpdateState);
            }
            mSysUpdater.downloadPackage();
            //}
        }
    }

    public void startCheckSystemUpdate() {
        if (mSysUpdater != null) {
            mSysUpdater.checkSystemupdate();
            mSysUpdateState = SYS_UPDATE_STATE.CHECKING;
            if (mOnSystemUpdaterChanged != null) {
                mOnSystemUpdaterChanged
                        .onSystemUpdateStateChanged(mSysUpdateState);
            }
        }
    }

    public String getSystemUpdateInfo() {
        return mUpdateInfo;
    }

    public void pause() {
        mSysUpdater.pauseDownloadPackage();
    }

    public String getPkgPath() {
        return mSysUpdater.getPkgPath();
    }

    public interface ISysUpdateListener {

        public void onError(boolean succed, int result);

    }

    /**
     * <b>Description: </b>系统更新相关回调<br/>
     * <b>Change History:</b><br/>
     * <table border="1">
     * <tr>
     * <td><b>user</b></td>
     * <td><b>date</b></td>
     * <td><b>time</b></td>
     * <td><b>reason</b></td>
     * </tr>
     * <tr>
     * <td>JunLuan@iflytek.com</td>
     * <td>2015年6月25日</td>
     * <td>下午7:36:13</td>
     * <td>创建此文件</td>
     * </tr>
     * </table>
     *
     * @author JunLuan@iflytek.com
     */
    public interface OnSystemUpdaterChanged {
        /**
         * onSystemUpdateStateChanged:更新状态改变. <br/>
         *
         * @param state 当前状态
         * @see SYS_UPDATE_STATE
         */
        void onSystemUpdateStateChanged(int state);

        /**
         * onSystemUpdateProgressChanged:更新进度改变. <br/>
         *
         * @param progress 当前进度， 0～100
         */
        void onSystemUpdateProgressChanged(int progress);

    }

    /**
     * @author JunLuan@iflytek.com
     */
    private static class SystemUpdaterInstance {
        private static final SystemUpdater INSTANCE = new SystemUpdater();
    }

    /**
     * <b>Description: </b>系统更新状态<br/>
     * <b>Change History:</b><br/>
     * <table border="1">
     * <tr>
     * <td><b>user</b></td>
     * <td><b>date</b></td>
     * <td><b>time</b></td>
     * <td><b>reason</b></td>
     * </tr>
     * <tr>
     * <td>JunLuan@iflytek.com</td>
     * <td>2015年6月25日</td>
     * <td>下午7:37:37</td>
     * <td>创建此文件</td>
     * </tr>
     * </table>
     *
     * @author JunLuan@iflytek.com
     */
    public class SYS_UPDATE_STATE {
        /**
         * 初始状态
         */
        public static final int INIT = 0;
        /**
         * 检查状态
         */
        public static final int CHECKING = INIT + 1;
        /**
         * 检查失败
         */
        public static final int CHECK_FAILED = CHECKING + 1;
        /**
         * 检查成功
         */
        public static final int CHECKED = CHECK_FAILED + 1;
        /**
         * 下载中
         */
        public static final int DOWNLOADING = CHECKED + 1;
        /**
         * 下载失败
         */
        public static final int DOWNLOAD_FAILED = DOWNLOADING + 1;
        /**
         * 下载完成
         */
        public static final int DOWNLOADED = DOWNLOAD_FAILED + 1;
        public static final int DOWNLOAD_PAUSED = DOWNLOADED + 1;
    }
}
